#ifndef ESP_UFFS_H__
#define ESP_UFFS_H__

#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
#include <unistd.h>
#include <utime.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include <sys/types.h>
#include <sys/reent.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <dirent.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_vfs.h"
#include "uffs_config.h"
#include "uffs_os.h"
#include "uffs_device.h"
#include "uffs_flash.h"
#include "uffs_mtb.h"
#include "uffs_fs.h"
#include "uffs_mem.h"
#include "uffs_fd.h"
#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief Last Modified Time
 *
 */
#define UFFS_ATTR_MTIME ((uint8_t) 't')

/**
 *Configuration structure for esp_vfs_uffs_register.
 */
typedef struct {
    const char *base_path;            /**< Mounting point. */
    uint8_t format_if_mount_failed:1; /**< Format the file system if it fails to mount. */
    uint8_t dont_mount:1;             /**< Don't attempt to mount or format. Overrides format_if_mount_failed */
    uffs_FlashOps ops;
} esp_vfs_uffs_conf_t;
/**
 * @brief uffs definition structure
 */
typedef struct {

    SemaphoreHandle_t lock;                   /*!< FS lock */
    char base_path[ESP_VFS_PATH_MAX+1];       /*!< cfg Mount point */
    char uffs_base_path[ESP_VFS_PATH_MAX+1];  /*!< uffs Mount point */
    uffs_MountTable mtbl;
    void *context;
} esp_uffs_t;
/**
 * Register and mount uffs to VFS with given path prefix.
 *
 * @param   conf                      Pointer to esp_vfs_uffs_conf_t configuration structure
 *
 * @return  
 *          - ESP_OK                  if success
 *          - ESP_ERR_NO_MEM          if objects could not be allocated
 *          - ESP_ERR_INVALID_STATE   if already mounted or partition is encrypted
 *          - ESP_ERR_NOT_FOUND       if partition for uffs was not found
 *          - ESP_FAIL                if mount or format fails
 */
esp_err_t esp_vfs_uffs_register(const esp_vfs_uffs_conf_t * conf);

/**
 * Unregister and unmount uffs from VFS
 *
 * @param partition_label  mount_point to unregister.
 *
 * @return  
 *          - ESP_OK if successful
 *          - ESP_ERR_INVALID_STATE already unregistered
 */
esp_err_t esp_vfs_uffs_unregister(const char *mount_point);

/**
 * Check if uffs is mounted
 *
 * @param mount_point  mount point check.
 *
 * @return  
 *          - true    if mounted
 *          - false   if not mounted
 */
bool esp_uffs_mounted(const char* mount_point);

/**
 * Format the uffs
 *
 * @param uffs  uffs.
 * @return  
 *          - ESP_OK      if successful
 *          - ESP_FAIL    on error
 */
int esp_uffs_format(esp_uffs_t * uffs);

/**
 * Get information for uffs
 *
 * @param mount_point               Optional, mount_point to get info for.
 * @param[out] total_bytes          Size of the file system
 * @param[out] used_bytes           Current used bytes in the file system
 *
 * @return  
 *          - ESP_OK                  if success
 *          - ESP_ERR_INVALID_STATE   if not mounted
 */
esp_err_t esp_uffs_info(const char* mount_point, size_t *total_bytes, size_t *used_bytes);

#if CONFIG_uffs_HUMAN_READABLE
/**
 * @brief converts an enumerated lfs error into a string.
 * @param uffs_errno The enumerated uffs error.
 */
const char * esp_uffs_errno(int uffs_errno);
#endif

#ifdef __cplusplus
} // extern "C"
#endif

#endif
